import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by Administrator on 2017/6/19.
 */
public class MultiplexerTimeServer implements Runnable {

    private Selector selector;

    private ServerSocketChannel serverSocketChannel;

    private volatile  boolean stop;

    public void stop()
    {
        stop=true;
    }

   //构造方法
    public MultiplexerTimeServer(int port ) {
     try{
         //创建多路复用
       selector=Selector.open();
       serverSocketChannel=ServerSocketChannel.open();
       //设置异步非堵塞
       serverSocketChannel.configureBlocking(false);
       serverSocketChannel.socket().bind(new InetSocketAddress(port));
       //讲服务端channel注册到,监听op_accept
       serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
       System.out.println("server is start");
     }
     catch (Exception ex)
     {
         ex.printStackTrace();
         System.exit(1);
     }

    }

    @Override
    public void run() {

        while (!stop)
        {
            try {
                //唤醒selector返回就绪状态的channel
                selector.select(1000);
                Set<SelectionKey> selectionKeys=selector.selectedKeys();
                Iterator<SelectionKey> it =selectionKeys.iterator();
                SelectionKey key=null;
                while (it.hasNext())
                {
                    key=it.next();
                    it.remove();
                    try {
                        handlerInput(key);
                    }
                    catch (Exception ex)
                    {
                        ex.printStackTrace();
                        if (key!=null)
                        {
                            key.cancel();
                            if (key.channel()!=null)
                            {
                                key.channel().close();
                            }
                        }
                    }
                }


            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    //袭击如客户端的请求消息
    private void handlerInput(SelectionKey key) throws IOException{
        if (key.isValid())
        {
            //处理客户端新请求
            if (key.isAcceptable())
            {
                //accept the new connection
                ServerSocketChannel serverSocketChannel= (ServerSocketChannel) key.channel();
                SocketChannel socketChannel=serverSocketChannel.accept();
                socketChannel.configureBlocking(false);
                //注册新联机到selector
                socketChannel.register(selector,SelectionKey.OP_READ);

            }
            //完成tcp三次握手
            if (key.isReadable())
            {
                //读数据
                SocketChannel socketChannel= (SocketChannel) key.channel();
                ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
                int readBytes=socketChannel.read(byteBuffer);
                if (readBytes>0)
                {
                    byteBuffer.flip();
                    byte[] bytes=new byte[byteBuffer.remaining()];
                    byteBuffer.get(bytes);
                    String body=new String(bytes,"UTF-8");
                    System.out.println("the time server receive order:"+body);
                    String currentTime="QUERY TIM ORDER".equalsIgnoreCase(body)?String.valueOf(System.currentTimeMillis()
                    ):"BAD ORDER";
                    doWrite(socketChannel,currentTime);
                }else if (readBytes<0){
                    key.cancel();
                    socketChannel.close();
                }
                else
                {

                }
            }

        }
    }

    private void doWrite(SocketChannel socketChannel,String response) throws IOException {
        if (response!=null&&response.trim().length()>0)
        {
            byte[] bytes=response.getBytes();
            ByteBuffer byteBuffer=ByteBuffer.allocate(bytes.length);
            //放入缓冲区
            byteBuffer.put(bytes);
            byteBuffer.flip();
            socketChannel.write(byteBuffer);
        }
    }

}
